home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!mcnc!gatech!mandrill!hal!ncoast!allbery
- From: athey@cod.nosc.mil (The Bit Butcher)
- Newsgroups: comp.sources.misc
- Subject: v03i075: "can" a fast "C" version, a great alias for "rm"
- Message-ID: <8807072011.AA08841@cod.nosc.mil>
- Date: 7 Jul 88 20:11:06 GMT
- Sender: allbery@ncoast.UUCP
- Reply-To: athey@cod.nosc.mil (The Bit Butcher)
- Lines: 884
- Approved: allbery@ncoast.UUCP
-
- Posting-number: Volume 3, Issue 75
- Submitted-by: "The Bit Butcher" <athey@cod.nosc.mil>
- Archive-name: can2
-
- This is a "C" version of an earlier posting of mine. It is a
- great alias for "rm". It moves the file to your personal trashcan.
- If you are consistently bothered by users or are a user yourself
- who is bothered by you own ineptitude in removal of files you
- realize you really don't want gone then this is just the thing for
- you. Enjoy.
-
- Yes, I know that this is amazingly similiar to the "rmunrm"
- package that can be found at simtel20, but I just thought that since
- mine is pretty fast and has some nice options, at least as far
- as I am concerned. One thing that the other package does that I
- don't is preserve directories. In other words, if you "can" two
- files with the same name you will only have the last one you "can"ned.
-
- -the bit butcher
-
- mail me: athey@nosc.mil
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: ReadMe Makefile.BSD Makefile.SUN Makefile.SYSV can.1 can.c
- # can.h emptytrash emptytrash.8 recurcan.c xdevcan.c
- # Wrapped by athey@unicorn on Thu Jul 7 10:35:01 1988
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'ReadMe' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ReadMe'\"
- else
- echo shar: Extracting \"'ReadMe'\" \(2456 characters\)
- sed "s/^X//" >'ReadMe' <<'END_OF_FILE'
- XWell, I am back again and you may not be rejoicing.
- X
- XThis is CAN 2.0.
- XYes it is all (almost all) new.
- X
- XFirst, what you need to do to make this nifty thing for yourself
- Xor your system (if you are the system manager)
- X
- X1. Copy the appropriate Makefile to Makefile and then compile.
- X2. Edit emptytrash to make it look in the trashcans of your system.
- X3. Install all of this wonderful stuff (Don't forget the man pages).
- X Make sure to make "emptytrash" executable by the crontab that will run it.
- X
- XSecond, So why have you wasted my time again or why version 2.0?
- X
- X1. Well, I rewrote the entire can in C. This made it move twice as fast.
- X Still a little slower than rm but certainly much nicer.
- X2. In the process of rewriting it, I added the verbose option and the
- X interactive option.
- X
- XThird, There are some things about this that you should know.
- X
- X1. This is my first attempt at a "C" utility but as far as I can tell,
- X it does the trick.
- X2. It only changes the access time, not the modification time and then
- X empties trash on the basis of access time. So, if you are really
- X hard-core, you can see if the one you removed and then recovered is
- X really the version you want.
- X3. This has the same handicap as my original script. You can only recover
- X one file at a time, and you must know it's specific name. If I have
- X time I will try my best to fix this problem.
- X4. The listing option is very primitive but since it traverses the
- X directory tree by where it is placed, the last things canned are
- X usually at the end of the list. I, once again, will do what I can
- X to repair these features (bugs?).
- X5. This is my first time passing around multiple system designs.
- X If I have a poor conception of what any system is like please let
- X me know at the address below. (rhyme?)
- X6. You may have the possibility of a pathname greater than 80. I rarely do.
- X To remedy any problems caused by this, simply change the define
- X entitled MAXPATHLEN.
- X7. May be possible to add a force option, but I don't see the necessity
- X of it right now.
- X
- XIf you have any complaints or you have bug fixes or
- Xanything of the sort please write me at
- X
- X "athey@nosc.mil"
- X
- XPlease write me if you install this and find it useful.
- XJust a quick note would be great, everybody.
- XI mean let me know if I should keep posting this artwork (junk?).
- X -the bit butcher
- X
- XNOTE: CAN 2.01 now we can deal with cross device canning.
- XNOTE: CAN 2.02 segmented and cleaned code.
- END_OF_FILE
- if test 2456 -ne `wc -c <'ReadMe'`; then
- echo shar: \"'ReadMe'\" unpacked with wrong size!
- fi
- # end of 'ReadMe'
- fi
- if test -f 'Makefile.BSD' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile.BSD'\"
- else
- echo shar: Extracting \"'Makefile.BSD'\" \(307 characters\)
- sed "s/^X//" >'Makefile.BSD' <<'END_OF_FILE'
- XCFLAGS = -O -DBSD
- X
- XDEST = /cd441/athey/bin
- X
- XLIBS =
- X
- XLINKER = cc
- X
- XMAKEFILE = Makefile
- X
- XOBJS = can.o recurcan.c xdevcan.c
- X
- XPROGRAM = can
- X
- XSRCS = can.c
- X
- Xall: $(PROGRAM)
- X
- X$(PROGRAM): $(OBJS)
- X $(LINKER) $(OBJS) $(LIBS) -o $(PROGRAM)
- X
- Xclean:; rm -f $(OBJS)
- END_OF_FILE
- if test 307 -ne `wc -c <'Makefile.BSD'`; then
- echo shar: \"'Makefile.BSD'\" unpacked with wrong size!
- fi
- # end of 'Makefile.BSD'
- fi
- if test -f 'Makefile.SUN' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile.SUN'\"
- else
- echo shar: Extracting \"'Makefile.SUN'\" \(307 characters\)
- sed "s/^X//" >'Makefile.SUN' <<'END_OF_FILE'
- XCFLAGS = -O -DSUN
- X
- XDEST = /cd441/athey/bin
- X
- XLIBS =
- X
- XLINKER = cc
- X
- XMAKEFILE = Makefile
- X
- XOBJS = can.o recurcan.c xdevcan.c
- X
- XPROGRAM = can
- X
- XSRCS = can.c
- X
- Xall: $(PROGRAM)
- X
- X$(PROGRAM): $(OBJS)
- X $(LINKER) $(OBJS) $(LIBS) -o $(PROGRAM)
- X
- Xclean:; rm -f $(OBJS)
- END_OF_FILE
- if test 307 -ne `wc -c <'Makefile.SUN'`; then
- echo shar: \"'Makefile.SUN'\" unpacked with wrong size!
- fi
- # end of 'Makefile.SUN'
- fi
- if test -f 'Makefile.SYSV' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile.SYSV'\"
- else
- echo shar: Extracting \"'Makefile.SYSV'\" \(327 characters\)
- sed "s/^X//" >'Makefile.SYSV' <<'END_OF_FILE'
- XCFLAGS = -O -DSYSV
- X
- XDEST = /cd441/athey/bin
- X
- XLIBS = -lndir -ljobs
- X
- XLINKER = cc
- X
- XMAKEFILE = Makefile
- X
- XOBJS = can.o recurcan.o xdevcan.o
- X
- XPROGRAM = can
- X
- XSRCS = can.c
- X
- Xall: $(PROGRAM)
- X
- X$(PROGRAM): $(OBJS) can.h
- X $(LINKER) $(OBJS) $(LIBS) -o $(PROGRAM)
- X
- Xclean:; rm -f $(OBJS)
- END_OF_FILE
- if test 327 -ne `wc -c <'Makefile.SYSV'`; then
- echo shar: \"'Makefile.SYSV'\" unpacked with wrong size!
- fi
- # end of 'Makefile.SYSV'
- fi
- if test -f 'can.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'can.1'\"
- else
- echo shar: Extracting \"'can.1'\" \(1788 characters\)
- sed "s/^X//" >'can.1' <<'END_OF_FILE'
- X.\" @(#)run.1 10.2 (MASSCOMP) 8/14/86
- X.RL "local"
- X.TH CAN 1
- X.SH NAME
- Xcan \- a replacement for rm that is safe
- X.SH SYNOPSIS
- X\fB can [ ivlrR ] <file | directory> ...
- X.br
- X.ns
- X.SH DESCRIPTION
- X.I Can
- Xis often an alias of
- X.I rm(1).
- X.I Can
- Xworks similiarly, with the exception of putting things into a directory, in
- Xyour home directory, called ".trashcan."
- XThe
- X.B -i
- Xoption makes it interactive, querying for each "can"-ing.
- XThe
- X.B -v
- Xoption gives a verbose following of all activities of this command.
- XThe
- X.B -l
- Xoption will give you a listing of the "$HOME/.trashcan"
- Xdirectory.
- XThe
- X.B -r
- Xoption works recursively just the same as
- X.I rm(1).
- X.sp
- XThe
- X.B -R
- Xoption will retrieve a file from the "$HOME/.trashcan" without the hassle
- Xof looking for it. The
- X.B -R
- Xoption copies the file from the "$HOME/.trashcan" directory into the
- Xpresent working directory. This can only recover one file at a time and
- Xis the only option that requires an argument. You should
- Xnote that
- X.B -R
- Xwill destroy the file in the working directory if it has the same name
- Xas the file that is being recovered, so use with caution.
- XYou cannot use
- X.B -r
- Xand
- X.B -R
- Xin the same command and the file to be recoved must not have a directory
- Xname in it.
- X.sp
- XThe trash gets dumped everyday but only gets rid of things that
- Xare more than a week old. In other words, you have a week to get something
- Xback after you have
- X.I can
- Xned it.
- X.SH FILES
- X.TP 2.5i
- X$HOME/.trashcan
- XThe reservoir of canned files
- X.SH SEE ALSO
- X.I
- Xemptytrash(8), rm(1)
- X.SH BUGS
- XThe
- X.B -R
- Xoption does not work on wild cards. You have to know the
- Xexact name of a file in order to recover it with this command.
- X.sp
- XIf further bugs are found please report them.
- X.SH AUTHOR
- XThe Bit Butcher
- X.br
- XInspired by the original
- X.B can
- Xwhich was written by a Russ Sage.
- END_OF_FILE
- echo shar: 1 control character may be missing from \"'can.1'\"
- if test 1788 -ne `wc -c <'can.1'`; then
- echo shar: \"'can.1'\" unpacked with wrong size!
- fi
- # end of 'can.1'
- fi
- if test -f 'can.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'can.c'\"
- else
- echo shar: Extracting \"'can.c'\" \(6932 characters\)
- sed "s/^X//" >'can.c' <<'END_OF_FILE'
- X/*************************************************************
- X* can.c 2.0
- X*
- X* This is a utility to replace rm. I hope you like it
- X*
- X* written by "the bit butcher"
- X*
- X* 2.02 changed the error handling to cases and segmented the
- X* program into three pieces and now have "can.h"
- X* 28 June 1988
- X*
- X* 2.01 changed the way cross device problems are dealt with
- X* copy file from one system to the other
- X* before 28 June 1988
- X*************************************************************/
- X
- X#include "can.h"
- X
- Xchar CAN[MAXPATHLEN]; /* String containing .trashcan directory*/
- Xchar ANSWER[14]; /* String used for finding interactive response */
- Xint VERBOSE = 0; /* Set if Verbose is wanted */
- Xint INTERACTIVE = 0; /* Set if Interactive is wanted */
- Xlong TIME; /* Used to get the current time */
- XUTIMBUF TIMES; /* Structure used to change the access time */
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar** argv;
- X{
- X int c; /* which character in getopt */
- X DIR *DIRP; /* Used to list the directory by pointing at .trashcan */
- X struct direct *DP; /* Used to point at consecutive entries when listing */
- X char FILENAME[MAXPATHLEN]; /* String containing .trashcan/current file*/
- X char *ACTNAME; /* Points to filename without any leading directory */
- X struct stat BUF; /* Used to point to mode info about files */
- X int RECURSIVE = 0; /* Set if Recursive is wanted */
- X#ifdef SYSV
- X int UID; /* Variable holding user's ID */
- X#endif
- X#ifdef SUN
- X int UID; /* Variable holding user's ID */
- X#endif
- X#ifdef BSD
- X uid_t UID; /* Variable holding user's ID */
- X#endif
- X char TEMP[MAXPATHLEN]; /* Used for quick access of file names */
- X struct passwd *USERINFO; /* Structure used to find out $HOME dir */
- X extern int optind; /* used to step through arguments */
- X extern char *optarg; /* used to step through arguments */
- X int errflag = 0; /* Used to indicate errors in options */
- X void recurcan(); /* Say this is a void function */
- X
- X /* Find out the users ID */
- X if((UID= getuid()) == NULL)
- X {
- X fprintf(stderr, "Invalid Login: Who Are You!?!\n");
- X exit(0);
- X }
- X
- X /* Get his home directory from the passwd file */
- X USERINFO = getpwuid(UID);
- X if(USERINFO->pw_dir == NULL)
- X {
- X fprintf(stderr, "No Home Directory: check /etc/passwd !!!\n");
- X exit(0);
- X }
- X /* say where the trashcan will be */
- X sprintf(CAN, "%s/.trashcan", USERINFO->pw_dir);
- X
- X /* make sure there is a trashcan */
- X if (access(CAN, F_OK) != 0)
- X /* if not, make a trashcan */
- X if(mkdir(CAN, 004777) != 0)
- X {
- X perror("can");
- X exit(2);
- X }
- X
- X /* could add force (-f) option later, perhaps */
- X /* Let's look at the options */
- X while((c=getopt(argc, argv, "ivlR:r")) != EOF)
- X switch(c)
- X {
- X case 'l': /* list the contents by stepping through */
- X fprintf(stdout, "%s\n", CAN);
- X DIRP = opendir(CAN);
- X /* Could allow arguments for selective listing */
- X for(DP = readdir(DIRP); DP != NULL; DP= readdir(DIRP))
- X fprintf(stdout, "%s\n", DP->d_name);
- X closedir(DIRP);
- X exit(0);
- X break;
- X case 'v': /* Set the verbose mode */
- X VERBOSE++;
- X break;
- X case 'i': /* Set the interactive mode */
- X INTERACTIVE++;
- X break;
- X case 'R': /* Recover a file */
- X if(RECURSIVE) /* if recursive point out illegal option
- X combination */
- X {
- X errflag++;
- X break;
- X }
- X /* get name of file to recover */
- X strcpy(TEMP, optarg);
- X /* does it have a directory in its name ? (it should not) */
- X if((ACTNAME = strrchr(TEMP, '/')) != NULL)
- X {
- X fprintf(stderr, "can: cannot access %s\n", TEMP);
- X fprintf(stderr, " no directory names in Recovery\n");
- X continue;
- X }
- X else
- X /* name the actual file in the trashcan to get */
- X sprintf(FILENAME, "%s/%s", CAN, TEMP);
- X /* does it exist in the trashcan */
- X if(access(FILENAME, F_OK) != 0)
- X {
- X fprintf(stderr, "can: %s does not exist\n", TEMP);
- X continue;
- X }
- X /* interogate just in case */
- X if (INTERACTIVE)
- X {
- X fprintf(stdout, "can recover: %s\? ", TEMP);
- X fscanf(stdin, "%s", ANSWER);
- X if ((ANSWER[0] != 'y') && (ANSWER[0] != 'Y'))
- X continue;
- X }
- X /* get rid of file if it exists in current directory */
- X if (access(TEMP, F_OK) == 0)
- X if (unlink(TEMP) != 0)
- X {
- X perror("can");
- X continue;
- X }
- X /* get a new copy of the file into the working directory */
- X if (link(FILENAME, TEMP) != 0)
- X {
- X perror("can");
- X continue;
- X }
- X /* say it has been recycled */
- X fprintf(stdout, "%s: recovered\n", TEMP);
- X exit(0);
- X break;
- X case 'r': /* Let's get recursive */
- X RECURSIVE++;
- X break;
- X default: /* Errors in bad options */
- X errflag++;
- X break;
- X }
- X
- X /* say if there are some bad options */
- X if(errflag)
- X {
- X fprintf(stderr, "%s\n", USAGE);
- X exit(2);
- X }
- X
- X /* get the current time */
- X if((TIME =time(0)) == 0)
- X {
- X perror("can");
- X exit(2);
- X }
- X /* step through the arguments to see what to get rid of */
- X for( ; optind < argc; optind++)
- X {
- X strcpy(TEMP, argv[optind]); /* get the next argument */
- X stat(TEMP, &BUF); /* get file info about this file */
- X /* Check for the existence of a file that is not a directory */
- X if ((access(TEMP, F_OK) == 0) && (!(BUF.st_mode & 0040000)))
- X {
- X /* interogate */
- X if(INTERACTIVE != 0)
- X {
- X fprintf(stdout, "can %s\? ", TEMP);
- X fscanf(stdin, "%s", ANSWER);
- X if((ANSWER[0] != 'y') && (ANSWER[0] != 'Y'))
- X continue;
- X }
- X /* strip off directory names so we can trash it properly */
- X if((ACTNAME = strrchr(TEMP, '/')) != NULL)
- X sprintf(FILENAME, "%s%s", CAN, ACTNAME);
- X else
- X sprintf(FILENAME, "%s/%s", CAN, TEMP);
- X /* if it exists in the trashcan already get rid of it */
- X if (access(FILENAME, F_OK) == 0)
- X if(unlink(FILENAME) != 0)
- X {
- X perror("can3");
- X continue;
- X }
- X /* put it in the trashcan */
- X if(link(TEMP, FILENAME) != 0)
- X {
- X switch(errno)
- X {
- X case EXDEV:
- X crossdevcan(TEMP, FILENAME);
- X break;
- X default:
- X perror("can1");
- X continue;
- X }
- X }
- X /* get rid of the original */
- X if(unlink(TEMP) != 0)
- X {
- X perror("can4");
- X continue;
- X }
- X /* change the access time */
- X TIMES.actime= (time_t)TIME;
- X TIMES.modtime= BUF.st_mtime;
- X if(utime(FILENAME, &TIMES) != 0)
- X {
- X perror("can5");
- X continue;
- X }
- X /* tell them what we did if they want to know */
- X if(VERBOSE)
- X fprintf(stdout, "%s: canned\n", TEMP);
- X }
- X else
- X {
- X /* is this a directory? */
- X if(BUF.st_mode & 0040000)
- X {
- X if(RECURSIVE == 0) /* yes, then do recursion if OK */
- X fprintf(stderr, "cannot can: %s directory\n", TEMP);
- X else
- X {
- X if(INTERACTIVE != 0)
- X {
- X fprintf(stdout, "can check %s directory\? ", TEMP);
- X fscanf(stdin, "%s", ANSWER);
- X if((ANSWER[0] != 'y') && (ANSWER[0] != 'Y'))
- X continue;
- X }
- X recurcan(TEMP);
- X }
- X }
- X else /* the file does not exist */
- X perror("can6");
- X }
- X }
- X}
- END_OF_FILE
- if test 6932 -ne `wc -c <'can.c'`; then
- echo shar: \"'can.c'\" unpacked with wrong size!
- fi
- # end of 'can.c'
- fi
- if test -f 'can.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'can.h'\"
- else
- echo shar: Extracting \"'can.h'\" \(1096 characters\)
- sed "s/^X//" >'can.h' <<'END_OF_FILE'
- X/******************************************************************
- X*
- X* CAN.H
- X*
- X*
- X*
- X******************************************************************/
- X
- X#include <stdio.h>
- X#include <pwd.h>
- X#include <string.h>
- X#include <errno.h>
- X#include <fcntl.h>
- X#include <sys/types.h>
- X#include <sys/timeb.h>
- X#include <sys/file.h>
- X#include <sys/stat.h>
- X
- X#ifdef SYSV
- X#include <ndir.h>
- X#endif
- X
- X#ifdef SUN
- X#include <sys/dir.h>
- X#endif
- X
- X#ifdef BSD
- X#include <sys/dir.h>
- X#endif
- X
- X#define USAGE "usage: can [ivlrR] file ..."
- X#define MAXPATHLEN 80 /* Longest possible path name */
- X
- Xextern char CAN[]; /* String containing .trashcan directory*/
- Xextern char ANSWER[]; /* String used for finding interactive response */
- Xextern int VERBOSE; /* Set if Verbose is wanted */
- Xextern int INTERACTIVE; /* Set if Interactive is wanted */
- Xextern long TIME; /* Used to get the current time */
- Xextern int errno; /* Used to return the error value */
- Xtypedef struct utimbuf
- X{
- X time_t actime; /* access time */
- X time_t modtime; /* modification time */
- X} UTIMBUF; /* Structure used to change the access time */
- Xextern UTIMBUF TIMES;
- END_OF_FILE
- if test 1096 -ne `wc -c <'can.h'`; then
- echo shar: \"'can.h'\" unpacked with wrong size!
- fi
- # end of 'can.h'
- fi
- if test -f 'emptytrash' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'emptytrash'\"
- else
- echo shar: Extracting \"'emptytrash'\" \(472 characters\)
- sed "s/^X//" >'emptytrash' <<'END_OF_FILE'
- X: /bin/sh
- X
- X# EMPTYTRASH
- X# Executed from root crontab file every night.
- X# It finds all files in all users .traschan directories and gets
- X# rid of any file that has not been accessed or modified for more
- X# than 7 days. Note: this works in conjunction with can. can
- X# changes modifies the access time for a file when it moves the
- X# file to the user's .trashcan diretory.
- X
- Xfind /cd441/*/.trashcan -atime +7 -print | while read FILE
- Xdo
- X# echo $FILE
- X rm $FILE
- Xdone
- END_OF_FILE
- if test 472 -ne `wc -c <'emptytrash'`; then
- echo shar: \"'emptytrash'\" unpacked with wrong size!
- fi
- # end of 'emptytrash'
- fi
- if test -f 'emptytrash.8' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'emptytrash.8'\"
- else
- echo shar: Extracting \"'emptytrash.8'\" \(871 characters\)
- sed "s/^X//" >'emptytrash.8' <<'END_OF_FILE'
- X.\" @(#)run.1 10.2 (MASSCOMP) 8/14/86
- X.RL "local"
- X.TH EMPTYTRASH 8
- X.SH NAME
- Xemptytrash \- the trash collector used with
- X.I can
- X.SH SYNOPSIS
- X\fBemptytrash
- X.br
- X.ns
- X.SH DESCRIPTION
- X.I Emptytrash
- Xsimply looks into each $HOME/.trashcan and checks the last access time
- Xwhich is usually set by
- X.I can(1).
- XAnything that it finds that is more than seven days old it permanently
- Xremoves via
- X.I rm(1).
- XThis amount of time can be changed by changing the "7" in the script file.
- XThe best thing to do is to put this in your root crontab file and have it
- Xexecuted everyday.
- X.SH FILES
- X.TP 2.5i
- X$HOME/.trashcan
- XThe reservoir of canned files
- X.SH SEE ALSO
- X.I
- Xcan(1), rm(1)
- X.SH BUGS
- XOnly that this was a quicky and could be made better by having it accept an
- Xargument that would determine the amount of elapsed time to check for.
- X.SH AUTHOR
- XThe Bit Butcher
- X.br
- XWith the help of Steph Luse.
- END_OF_FILE
- if test 871 -ne `wc -c <'emptytrash.8'`; then
- echo shar: \"'emptytrash.8'\" unpacked with wrong size!
- fi
- # end of 'emptytrash.8'
- fi
- if test -f 'recurcan.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'recurcan.c'\"
- else
- echo shar: Extracting \"'recurcan.c'\" \(3460 characters\)
- sed "s/^X//" >'recurcan.c' <<'END_OF_FILE'
- X/************************************************************************
- X*
- X* RECURCAN.C
- X* this is used to traverse a directory tree when doing a
- X* recursive can passed the directory to be examined
- X*
- X************************************************************************/
- X
- X#include "can.h"
- X
- Xvoid recurcan(temp)
- Xchar *temp;
- X{
- X DIR *DIRP; /* Used to list the directory by pointing at .trashcan */
- X struct direct *DP; /* Used to point at consecutive entries when listing */
- X char FILENAME[MAXPATHLEN]; /* String containing .trashcan/current file*/
- X char *ACTNAME; /* Points to filename without any leading directory */
- X struct stat BUF; /* Used to point to mode info about files */
- X char TEMP[MAXPATHLEN]; /* this is used to look at the current file */
- X char WORKDIR[MAXPATHLEN]; /* the working directory we came from */
- X
- X DIRP = opendir(temp); /* open the directory being canned */
- X getwd(WORKDIR); /* get the current working directory */
- X chdir(temp); /* go to the directory to be canned */
- X /* get the next directory entry */
- X for(DP = readdir(DIRP); DP != NULL; DP= readdir(DIRP))
- X {
- X strcpy(TEMP, DP->d_name); /* put the name in TEMP */
- X stat(TEMP, &BUF); /* get some info about this file */
- X /* does it exist and is it not a directory */
- X if ((access(TEMP, F_OK) == 0) && (!(BUF.st_mode & 0040000)))
- X {
- X /* interogate */
- X if(INTERACTIVE != 0)
- X {
- X fprintf(stdout, "can %s\? ", TEMP);
- X fscanf(stdin, "%s", ANSWER);
- X if((ANSWER[0] != 'y') && (ANSWER[0] != 'Y'))
- X continue;
- X }
- X /* make the name of the trash file */
- X sprintf(FILENAME, "%s/%s", CAN, TEMP);
- X /* get rid of the trash version if there is one */
- X if (access(FILENAME, F_OK) == 0)
- X if(unlink(FILENAME) != 0)
- X {
- X perror("can7");
- X continue;
- X }
- X /* put file in the trash */
- X if(link(TEMP, FILENAME) != 0)
- X {
- X switch(errno)
- X {
- X case EXDEV:
- X crossdevcan(TEMP, FILENAME);
- X break;
- X default:
- X perror("can2");
- X continue;
- X }
- X }
- X /* get rid of the file here */
- X if(unlink(TEMP) != 0)
- X {
- X perror("can8");
- X continue;
- X }
- X /* change the access time */
- X TIMES.actime= (time_t)TIME;
- X TIMES.modtime= BUF.st_mtime;
- X if(utime(FILENAME, &TIMES) != 0)
- X {
- X perror("can9");
- X continue;
- X }
- X /* tell them what happened if they want to know */
- X if(VERBOSE)
- X fprintf(stdout, "%s: canned\n", TEMP);
- X }
- X else
- X {
- X /* is it a directory? */
- X if(BUF.st_mode & 0040000)
- X {
- X /* make sure it is not ".." or "." */
- X if((strcmp(TEMP,"..") != 0) && (strcmp(TEMP,".") != 0))
- X {
- X /* make sure they want to look at this directory */
- X if(INTERACTIVE != 0)
- X {
- X fprintf(stdout, "can check %s directory\? ", TEMP);
- X fscanf(stdin, "%s", ANSWER);
- X if((ANSWER[0] != 'y') && (ANSWER[0] != 'Y'))
- X continue;
- X }
- X /* get on with recursion using newest directory */
- X recurcan(TEMP);
- X }
- X }
- X else
- X perror("can10");
- X }
- X }
- X chdir(WORKDIR); /* go back to directory from which started */
- X closedir(DIRP); /* close the one we were canning */
- X /* make sure they want to get rid of the directory */
- X if(INTERACTIVE != 0)
- X {
- X fprintf(stdout, "can directory %s\? ", temp);
- X fscanf(stdin, "%s", ANSWER);
- X if((ANSWER[0] != 'y') && (ANSWER[0] != 'Y'))
- X return;
- X }
- X /* get rid of the directory */
- X if(rmdir(temp) != 0)
- X perror("can11");
- X else
- X /* tell them if they want to know */
- X if(VERBOSE)
- X fprintf(stdout, "%s: canned directory\n", temp);
- X}
- END_OF_FILE
- if test 3460 -ne `wc -c <'recurcan.c'`; then
- echo shar: \"'recurcan.c'\" unpacked with wrong size!
- fi
- # end of 'recurcan.c'
- fi
- if test -f 'xdevcan.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'xdevcan.c'\"
- else
- echo shar: Extracting \"'xdevcan.c'\" \(1664 characters\)
- sed "s/^X//" >'xdevcan.c' <<'END_OF_FILE'
- X/***********************************************************************
- X*
- X* XDEVCAN.C
- X* this is called and the file is copied via read and write to
- X* the other device, sure it may be slow but it solves a problem
- X* of cross device links crossdevcan(OLDFILE, NEWFILE)
- X*
- X***********************************************************************/
- X
- X#include "can.h"
- X
- Xcrossdevcan(OLDFILE, NEWFILE)
- Xchar *OLDFILE, *NEWFILE;
- X{
- X int oldFD, newFD; /* File Descriptors for access */
- X char NEXTCHAR[512]; /* used to transfer the char to new place */
- X int RWSIZE = 512; /* amount to read and write */
- X struct stat BUF; /* used to transfer all stats of old file to new */
- X int n_read; /* the number of bytes successfully read */
- X
- X /* create the new file in the trashcan */
- X if((newFD = creat(NEWFILE, 00777)) < 0)
- X {
- X perror("Cross Device can");
- X return;
- X }
- X /* open the old one to be read */
- X if((oldFD = open(OLDFILE, O_RDONLY)) < 0)
- X {
- X perror("Cross Device can");
- X return;
- X }
- X /* repeatedly read and write until whole file is copied */
- X while((n_read = read(oldFD, NEXTCHAR, RWSIZE)) != 0)
- X {
- X if((write(newFD, NEXTCHAR, n_read)) != n_read)
- X {
- X perror("Cross Device can");
- X return;
- X }
- X }
- X /* close the files */
- X close(oldFD);
- X close(newFD);
- X /* get info concerning the old file */
- X stat(OLDFILE, &BUF);
- X /* make the new file's modes the same as the old one's */
- X if(chmod(NEWFILE, (int)(BUF.st_mode & 0777)) != 0)
- X {
- X perror("Cross Device can");
- X return;
- X }
- X /* make the new file's times the same as the old one's */
- X TIMES.actime= BUF.st_atime;
- X TIMES.modtime= BUF.st_mtime;
- X if(utime(NEWFILE, &TIMES) != 0)
- X {
- X perror("Cross Device can");
- X return;
- X }
- X}
- END_OF_FILE
- if test 1664 -ne `wc -c <'xdevcan.c'`; then
- echo shar: \"'xdevcan.c'\" unpacked with wrong size!
- fi
- # end of 'xdevcan.c'
- fi
- echo shar: End of shell archive.
- exit 0
-